
const Prism = require('prismjs')
const escapeHtml = require("escape-html")
require('prismjs/components/prism-typescript')

const VueMdHeadHtmlMixin = {
  data() {
    return {
      _codeLines: 0
    }
  },
  methods: {
    getHtml(str, lang, highlight) {
      const code = this.getHtmlCode(str, lang)
      if (!str || !highlight) {
        return code
      }
      const addHightLine = this.getHighlihtLine(highlight)
      return addHightLine + '\n' + code
    },
    getHtmlCode(str, lang) {
      if (!lang) {
        return this.wrap(str, 'text')
      }
      const exlang = this.getLangCodeFromExtension(lang)
      const grammar = Prism.languages[exlang] || ''
      console.log('Prism.highlight grammar=', grammar)
      const text = Prism.highlight(str, grammar, exlang);
      return this.wrap(text, lang)
    },
    getLangCodeFromExtension(extension) {
      const extensionMap = {
        vue: 'markup',
        html: 'markup',
        md: 'markdown',
        rb: 'ruby',
        ts: 'typescript',
        py: 'python',
        sh: 'bash',
        yml: 'yaml',
        styl: 'stylus',
        kt: 'kotlin',
        rs: 'rust',
        js: 'javascript',
      }
      const exLang = extensionMap[extension] || extension
      return exLang
    },
    wrap(code, lang) {
      if (lang === 'text') {
        code = escapeHtml(code)
      }
      const textCode = `<pre v-pre class="language-${lang}"><code>${code}</code></pre>`
      const addLineCode = this.getLineNumber(textCode)

      return addLineCode
    },
    getLineNumber(rawCode) {
      const code = rawCode.slice(
        rawCode.indexOf('<code>'),
        rawCode.indexOf('</code>')
      )

      const lines = code.split('\n')
      this._codeLines = lines.length
      const lineNumbersCode = [...Array(lines.length - 1)]
        .map((line, index) => `<span class="line-number">${index + 1}</span><br>`).join('')

      const lineNumbersWrapperCode
        = `<div class="line-numbers-wrapper">${lineNumbersCode}</div>`

      // const finalCode = rawCode
      //   .replace('<!--beforeend-->', `${lineNumbersWrapperCode}<!--beforeend-->`)
      //   .replace('extra-class', 'line-numbers-mode')

      const finalCode = rawCode + `\n${lineNumbersWrapperCode}`

      return finalCode
    },
    getHighlihtLine(highlight) {
      const h = highlight || ''
      const token = h.split(',').map(v => v.split('-').map(v => parseInt(v, 10)))

      let highlightLinesCode = ''
      for (let i = 0; i < this._codeLines; i ++) {
        const lineNumber = i + 1
        const inRange = token.some(([start, end]) => {
          if (start && end) {
            return lineNumber >= start && lineNumber <= end
          }
          return lineNumber === start
        })
        if (inRange) {
          highlightLinesCode += `<div class="highlighted">&nbsp;</div> \n`
        } else {
          highlightLinesCode += `<br> \n`
        }
      }
      const highlightLinesWrapperCode = `<div class="highlight-lines">${highlightLinesCode}</div>`
      return highlightLinesWrapperCode
    },
  }
}

export default VueMdHeadHtmlMixin